﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace IRProject
{
    class StreamArray<T> : BaseStreamArray<T> where T : IConvertible
    {
        string fileName = Guid.NewGuid().ToString();

        public StreamArray(int size)
            : base(size)
        {
            int limit = 5000, tempSize = maxSize;

            using (BinaryWriter binWriter =
            new BinaryWriter(File.Open(fileName, FileMode.Create)))
            {
                byte[] dataArray;
                while (tempSize / limit > 1)
                {
                    dataArray = new byte[limit * 4];
                    binWriter.Write(dataArray);
                    tempSize -= limit;
                }

                dataArray = new byte[tempSize * 4];
                binWriter.Write(dataArray);
                dataArray = null;
            }
        }

        private void write(BinaryWriter binWriter, T value)
        {
            if (value is int)
            {
                int v = Convert.ToInt32(value);
                binWriter.Write(v);
            }
            if (value is float)
            {
                float v = Convert.ToSingle(value);
                binWriter.Write(v);
            }
        }

        private T Get(int index)
        {
            if (index >= maxSize)
                throw new IndexOutOfRangeException();
            T ans = default(T);//隨便初始
            if (File.Exists(fileName))
            {
                BinaryReader binReader =
                    new BinaryReader(File.Open(fileName, FileMode.Open));
                try
                {
                    if (binReader.PeekChar() != -1)
                    {
                        for (int i = 0; i < index; i++)
                        {
                            binReader.ReadSingle();
                        }
                        if (typeof(T) == typeof(int))
                        {
                            ans = (T)Convert.ChangeType(binReader.ReadInt32(), typeof(T));
                        }
                        if (typeof(T) == typeof(float))
                        {
                            ans = (T)Convert.ChangeType(binReader.ReadSingle(), typeof(T));
                        }
                    }
                }

                // If the end of the stream is reached before reading
                // the four data values, ignore the error and use the
                // default settings for the remaining values.
                catch (EndOfStreamException e)
                {
                    Console.WriteLine("{0} caught and ignored. " +
                        "Using default values.", e.GetType().Name);
                }
                finally
                {
                    binReader.Close();
                }
            }
            return ans;
        }

        private void Set(int index, T value)
        {
            if (index >= maxSize)
                throw new IndexOutOfRangeException();
            using (BinaryWriter binWriter =
                new BinaryWriter(File.Open(fileName, FileMode.Open)))
            {
                binWriter.Seek(index * 4, 0);
                write(binWriter, value);
            }
        }

        public override T this[int index]
        {
            get { return Get(index); }
            set { Set(index, value); }
        }

        public void DeleteTempFile()
        {
            if (System.IO.File.Exists(fileName))
            {
                // Use a try block to catch IOExceptions, to
                // handle the case of the file already being
                // opened by another process.
                try
                {
                    System.IO.File.Delete(fileName);
                }
                catch (System.IO.IOException e)
                {
                    Console.WriteLine(e.Message);
                    return;
                }
            }
        }
    }
}
